package middleware

import (
	"context"
	"net/http"
	"strconv"

	"github.com/ammyhaber/seckill/pkg/breaker"
	"github.com/ammyhaber/seckill/pkg/limiter"
	"github.com/ammyhaber/seckill/pkg/metrics"
)

// MetricsLimiterMiddleware 带指标收集的限流中间件
func MetricsLimiterMiddleware(limiter limiter.RateLimiter, metrics *metrics.LimiterMetrics) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// 记录请求
			metrics.RecordRequest()

			// 开始计时
			reqID := r.URL.Path + ":" + strconv.FormatInt(getRequestID(), 10)
			metrics.StartTimer(reqID)

			// 前置：判断是否允许请求通过
			if !limiter.Allow() {
				// 记录拒绝
				metrics.RecordRejected()
				metrics.StopTimer(reqID)

				w.Header().Set("Content-Type", "application/json")
				w.WriteHeader(http.StatusTooManyRequests)
				w.Write([]byte(`{"status":"error","message":"请求频率过高，请稍后再试"}`))
				return
			}

			// 记录允许
			metrics.RecordAllowed()

			// 请求通过，继续处理
			next.ServeHTTP(w, r)

			// 停止计时
			metrics.StopTimer(reqID)
		})
	}
}

// AdaptiveBreakerMiddleware 适应性熔断器中间件
func AdaptiveBreakerMiddleware(circuitBreaker interface{}, serviceName string, metrics *metrics.BreakerMetrics) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// 记录请求
			metrics.RecordRequest()

			// 开始计时
			reqID := r.URL.Path + ":" + strconv.FormatInt(getRequestID(), 10)
			metrics.StartTimer(reqID)

			// 根据类型获取执行方法和状态
			var execute func(func() error) error
			var getState func() int

			switch cb := circuitBreaker.(type) {
			case BreakerExecutor:
				execute = cb.Execute
				getState = cb.GetState
			case *breaker.AdaptiveBreaker:
				execute = cb.Execute
				getState = cb.GetState
			default:
				// 不支持的类型，返回内部服务器错误
				w.WriteHeader(http.StatusInternalServerError)
				w.Write([]byte("不支持的熔断器类型"))
				return
			}

			// 记录当前状态
			metrics.RecordState(getState())

			// 包装ResponseWriter以捕获状态码
			ww := NewResponseWriterWrapper(w)

			// 执行请求
			err := execute(func() error {
				next.ServeHTTP(ww, r)

				// 检查状态码，如果是5xx则返回错误
				if ww.Status >= 500 {
					return httpServerError{
						status: ww.Status,
						url:    r.URL.Path,
					}
				}
				return nil
			})

			// 处理熔断器错误
			if err != nil {
				// 如果是熔断器开启错误，返回服务不可用
				if isCircuitOpenError(err) {
					metrics.RecordRejected()

					w.Header().Set("Content-Type", "application/json")
					w.WriteHeader(http.StatusServiceUnavailable)
					w.Write([]byte(`{"status":"error","message":"服务暂时不可用，请稍后再试"}`))
				}

				metrics.RecordFailure()
			} else {
				metrics.RecordSuccess()
			}

			// 停止计时
			metrics.StopTimer(reqID)
		})
	}
}

// BreakerExecutor 熔断器执行器接口
type BreakerExecutor interface {
	Execute(func() error) error
	GetState() int
	Reset()
	ExecuteWithResult(ctx context.Context, key string, fn func() (interface{}, error)) (interface{}, error)
}

// httpServerError 表示HTTP服务器错误
type httpServerError struct {
	status int
	url    string
}

// Error 实现error接口
func (e httpServerError) Error() string {
	return "HTTP服务器错误: " + e.url + " 状态码: " + strconv.Itoa(e.status)
}

// isCircuitOpenError 检查是否是熔断器开启错误
func isCircuitOpenError(err error) bool {
	// 根据您的熔断器实现检查错误类型
	return err != nil && (err.Error() == "熔断器开启，请求被拒绝" ||
		err.Error() == "自适应熔断器开启，请求被拒绝" ||
		err.Error() == "服务降级，使用备用方案")
}

// 生成请求ID的计数器
var requestIDCounter int64 = 0

// getRequestID 获取唯一的请求ID
func getRequestID() int64 {
	requestIDCounter++
	return requestIDCounter
}
